//////////////////////////////////////////////////////////////////////////////////
//                                                                              //
//  This file is part of the buola project (https://code.google.com/p/buola/).  //
//                                                                              //
//  Copyright(c) 2007-2012 Xavi Gratal                                          //
//  gratal AT gmail DOT com                                                     //
//                                                                              //
//  Buola is free software: you can redistribute it and/or modify               //
//  it under the terms of the GNU General Public License as published by        //
//  the Free Software Foundation, either version 3 of the License, or           //
//  (at your option) any later version.                                         //
//                                                                              //
//  Buola is distributed in the hope that it will be useful,                    //
//  but WITHOUT ANY WARRANTY; without even the implied warranty of              //
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               //
//  GNU General Public License for more details.                                //
//                                                                              //
//  You should have received a copy of the GNU General Public License           //
//  along with buola.  If not, see <http://www.gnu.org/licenses/>.              //
//                                                                              //
//////////////////////////////////////////////////////////////////////////////////

#include "general.h"

#include <buola/io/filesystem.h>

#include <buola/db/cdbstringset.h>

#include "sql_media.h"

CMediaServer::CMediaServer()
	:	dbus::CObject<CMediaServer>("/org/buola/BigBrother/Media")
{
    InitDatabase();
}

CMediaServer::~CMediaServer()
{
}

void CMediaServer::InitDatabase()
{
    mDB.Create("sqlite");

    OpenDatabase();
    PrepareQueries();
}

void CMediaServer::OpenDatabase()
{
    using namespace sql_media;

    io::CURI lURI=io::get_home()/".buola"/"bb"/"media.db";
    bool lExisted=io::exists(lURI);

    mDB.SetURI(lURI);
    mDB.Connect();

    mDB.Exec(sPragmas);

    if(!lExisted)
    {
        mDB.Exec(sCreateTables);
        mDB.Exec(sDefaultData);
    }
}

void CMediaServer::PrepareQueries()
{
    using namespace sql_media;

    mQueries.mInsertFolder.Create(mDB,sInsertFolder);
    mQueries.mInsertItem.Create(mDB,sInsertItem);
    mQueries.mInsertItemData.Create(mDB,sInsertItemData);
    mQueries.mGetFolderID.Create(mDB,sGetFolderID);

    CDBStringSet lSet(mDB,"Folders","FolderID","URL");
}

int CMediaServer::CreateFolder(const std::string &pFolder)
{
    CDBQueryRun lQ(mQueries.mInsertFolder);
    lQ.BindAll(pFolder);
    lQ.Exec();

    return lQ.GetLastInsertID();
}

int CMediaServer::GetFolderID(const std::string &pFolder,bool pCreate)
{
    using namespace sql_media;

    CDBQueryRun lQ(mQueries.mGetFolderID);

    lQ.BindAll(pFolder);
    lQ.Exec();

    if(lQ.NextRow())
        return lQ.Column<int>(0);

    if(pCreate)
        return CreateFolder(pFolder);
    else
        return -1;
}

void CMediaServer::InsertItemData(int pItemID,const std::string &pKey,const std::string &pValue)
{
    using namespace sql_media;

    CDBQueryRun lQ(mQueries.mInsertItemData);
    lQ.BindAll(pItemID,pKey,pValue);
    lQ.Exec();
}

void CMediaServer::AddMediaItem(const io::CURI &pURI,const std::string &pMime,const std::map<std::string,std::string> &pData)
{
    using namespace sql_media;

    CDBTransaction lTransaction(mDB);

    int lFolder=GetFolderID(pURI.GetParent().ToString(),true);

    CDBQueryRun lQ(mQueries.mInsertItem);
    lQ.BindAll(pURI.ToString(),lFolder,pMime);
    lQ.Exec();
    int lItemID=lQ.GetLastInsertID();

//    GetSpecializedInserter(pMime)->InsertData(lItemID,pMime,pData);
    for(std::map<std::string,std::string>::const_iterator i=pData.begin();i!=pData.end();++i)
    {
        InsertItemData(lItemID,i->first,i->second);
    }

    lTransaction.Commit();
}
